﻿// Copyright (c) 2013 Bryan C. O'Connell
// http://wsubi.codeplex.com/license
// Purpose: Pretty simple - this is the interactive console. 

using System;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Configuration;
using System.Collections.Generic;

namespace Wsubi
{
    class AppConsole
    {
        // Stores the most recent command entered.
        private static Command _UserCommand;

        // Stores, manages and provides information on all scripts and related files during runtime.
        private static Itamae _Chef;

        // Stores a list of Shorcut commands from the designated 'Shortcuts' file.
        private static Shortcuts _MyShortcuts;

        // Location on disk to store any files that are output by wsubi. 
        private static string _OutputFolder = String.Empty;

        static void Main()
        {
            Console.WriteLine("wsubi - a spiced-up way to manage your scripts for Windows.");
            Console.WriteLine("Find out more: http://wsubi.codeplex.com");
            Console.WriteLine("For a list of available commands and usage details, enter 'help ?'." + "\n");
            
            ChefPrep();

            // Do an initial Roll to gather all of the script information into memory.
            _UserCommand = new Command("roll *");
            AskForRolls();

            // Read shortcuts into memory for reference.
            GetShortcuts();

            // Designate a place for files to be created.
            SetOutputFolder();

            // Load console and wait for user commands.
            while (_Chef.Ready) {

                Console.Write("\n[~wsubi]: ");
                string Input = Console.ReadLine();

                _UserCommand = new Command(Input);
                RunCommand();
            }

            Console.WriteLine("Quitting wsubi. Press any key to exit ... ");
            Console.ReadKey(true);
        }

        /// <summary>Initializes local instance of Itamae class (the chef).</summary>
        private static void ChefPrep()
        {
            try
            {
                _Chef = new Itamae(ConfigurationManager.AppSettings["ScriptsFolder"]);
            }
            catch (Exception ex)
            {
                Informant.DisplayError("So sorry, a preparation problem occured.", ex);
            }
        }

        /// <summary>Retrieve the list of user-created shortcuts.</summary>
        private static void GetShortcuts()
        {
            try
            {
                _MyShortcuts = new Shortcuts(ConfigurationManager.AppSettings["ShortcutsFile"]);
            }
            catch (Exception ex)
            {
                Informant.DisplayError("So sorry, there was a problem loading your Shortcuts file.", ex);
            }
        }

        /// <summary>Set the location on disk to store any files that are output by wsubi.
        /// This should come from the app.config file. If the setting is missing, or the folder 
        /// doesn't exist, just use whatever folder wsubi.exe is currently running from.</summary>
        private static void SetOutputFolder()
        {
            string ConfigSetting_OutputFolder = ConfigurationManager.AppSettings["OutputFolder"];

            if ((String.IsNullOrEmpty(ConfigSetting_OutputFolder)) || (!Directory.Exists(ConfigSetting_OutputFolder)))
            {
                _OutputFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            }
            else
            {
                _OutputFolder = ConfigSetting_OutputFolder;
            }
        }

        /// <summary>Executes the stored _UserCommand.</summary>
        private static void RunCommand()
        {
            try
            {
                switch (_UserCommand.CommandType)
                {
                    case CommandTypes.Help:
                        Informant.ShowHelp(_UserCommand.Target);
                        break;

                    case CommandTypes.Info:
                        _Chef.ProvideInfo(_UserCommand);
                        DeliverOrder();
                        break;

                    case CommandTypes.List:
                        _Chef.ListScripts(_UserCommand);
                        DeliverOrder();
                        break;

                    case CommandTypes.Queue:
                        ProcessQueue(_UserCommand.Target);
                        break;

                    case CommandTypes.Query:
                        _Chef.ExecuteQuery(_UserCommand);
                        DeliverOrder();
                        break;

                    case CommandTypes.Roll:
                        ChefPrep();
                        AskForRolls();
                        break;

                    case CommandTypes.Run:
                        // '~' is the shortcut indicator. If present, the user is requesting a replacement 
                        // from their designated 'ShortcutsFile' file.It needs to be retreived from memory, 
                        // and a new _UserCommand must be built with the value.
                        if (_UserCommand.Target.StartsWith("~"))
                        {
                            string RequestedShortcut = _MyShortcuts.GetShortcutValue(_UserCommand.Target.Substring(1));
                            _UserCommand = new Command("run " + RequestedShortcut);
                        }

                        _Chef.RunScript(_UserCommand);
                        break;

                    case CommandTypes.Search:
                        _Chef.SearchScripts(_UserCommand);
                        DeliverOrder();                       
                        break;

                    default:
                        Console.WriteLine("Unknown or invalid command. Please try again.");
                        break;
                }
            }
            catch (Exception ex)
            {
                Informant.DisplayError("So sorry, there was an problem executing your '" + _UserCommand.Action + "' command.", ex);
            }
        }

        /// <summary>Order up! Display information generated by a wsubi command back to the user.</summary>
        private static void DeliverOrder()
        { 
            switch(_Chef.CurrentOrder.Presentation)
            {
                case OutputsTo.File:
                    string OutputFile = _OutputFolder + "\\" + _UserCommand.Target + ".txt";
                    Informant.WriteContentToFile(_Chef.CurrentOrder.Results, OutputFile);
                    Console.WriteLine("\nFile created: " + OutputFile);
                    break;

                case OutputsTo.Screen:
                    Informant.DisplayFormattedResults(_Chef.CurrentOrder.Results);
                    break;

                default:
                    Console.WriteLine("So sorry, order could not be delivered. Unknown presentation requested.");
                    break;
            }
        }

        /// <summary>Asks the _Chef to re-roll all of the script files.</summary>
        private static void AskForRolls()
        { 
            try 
            {
                Console.Write("Rolling scripts ... ");

                _Chef.MakeRolls(_UserCommand);

                Console.Write("Done!\n");
            } 
            catch (Exception ex) 
            {
                Informant.DisplayError("So sorry, there was a problem rolling your scripts.", ex);
            }
        }

        /// <summary>Runs all commands in the specified Queue file.</summary>
        private static void ProcessQueue(string QueueFile)
        {             
            try
            {
                Queue QueueList = new Queue(QueueFile);
                int CommandCount = 0;

                foreach (string UserCommand in QueueList.CommandQueue)
                {
                    ++CommandCount;

                    Console.WriteLine("Processing Queue Command #" + CommandCount + " of #" + QueueList.CommandQueue.Count);
                    Console.WriteLine("Command = " + UserCommand + " ... ");

                    _UserCommand = new Command(UserCommand);
                    RunCommand();
                }

                Console.WriteLine("Done!");   
            }
            catch (Exception ex)
            {
                Informant.DisplayError("So sorry, there was a problem processing your Queue.", ex);
            }            
        }
    }
}
